﻿using System;
using System.IO;

namespace MinecraftBackupAssistant
{
    public static class SimpleFileCopy
    {
        /// <summary>
        /// Returns the total size of the directory and it's contents
        /// </summary>
        /// <param name="directory">Directory to get the size of</param>
        /// <returns></returns>
        public static long GetDirectorySize(DirectoryInfo directory)
        {
            return CalculateDirectorySize(directory, 0);
        }

        /// <summary>
        /// Copies the contents of a directroy to the target destination
        /// Calls itself recursively on any subfolder in the directory
        /// </summary>
        /// <param name="dirToCopy">The directory to copy</param>
        /// <param name="destinationPath">The destination directory</param>
        public static void CopyDirectory(DirectoryInfo dirToCopy, string destinationPath)
        {
            long sizeCopied = 0;
            CopyDirectory(dirToCopy, destinationPath, ref sizeCopied, 0, null);
        }

        /// <summary>
        /// Copies the contents of a directroy to the target destination while reporting the progress through the Action delegate
        /// Calls itself recursively on any subfolder in the directory
        /// </summary>
        /// <param name="dirToCopy">The directory to copy</param>
        /// <param name="destinationPath">The destination directory</param>
        /// <param name="action">The action which progress is reported through. Recieves a value between 0 and 1 indicationg progress in percent</param>
        public static void CopyDirectoryWithProgress(DirectoryInfo dirToCopy, string destinationPath, Action<double> action)
        {
            long dirSize = GetDirectorySize(dirToCopy);
            long sizeCopied = 0;
            CopyDirectory(dirToCopy, destinationPath, ref sizeCopied, dirSize, action);
        }

        private static void CopyDirectory(DirectoryInfo dirToCopy, string destinationPath, ref long sizeCopied, long totalSize, Action<double> action)
        {
            DirectoryInfo destinationDir = new DirectoryInfo(destinationPath);
            if (destinationDir.Exists == false)
            {
                destinationDir.Create();
            }

            foreach (FileInfo file in dirToCopy.GetFiles())
            {
                file.CopyTo(Path.Combine(destinationPath, file.Name));
                if (action != null)
                {
                    sizeCopied += file.Length;
                    action(sizeCopied/(double)totalSize);
                }
            }

            // Makes a recursive call to itself for each subfolder in the current working directory
            foreach (DirectoryInfo directory in dirToCopy.GetDirectories())
            {
                CopyDirectory(directory, Path.Combine(destinationPath, directory.Name), ref sizeCopied, totalSize, action);
            }
        }

        private static long CalculateDirectorySize(DirectoryInfo directory, long startSize)
        {
            foreach (DirectoryInfo dir in directory.GetDirectories())
            {
                startSize = CalculateDirectorySize(dir, startSize);
            }

            foreach (FileInfo file in directory.GetFiles())
            {
                startSize += file.Length;
            }

            return startSize;
        }
    }
}
